﻿using System.ComponentModel;
using System.Windows.Controls;
using StepsManagerLibrary.Annotations;
using StepsManagerLibrary.Enum;
using StepsManagerLibrary.Events;
using StepsManagerLibrary.Interfaces;

namespace StepsManagerUILibrary
{
    public class BaseWPFUserControl : UserControl, IStepControl
    {
        #region Fields

        private readonly BaseStepControl _stepControl;

        #endregion

        #region Constructors

        public BaseWPFUserControl()
            : this("")
        {
        }

        public BaseWPFUserControl(string title)
        {
            _stepControl = new BaseStepControl(title);
            _stepControl.PropertyChanged += StepControlOnPropertyChanged;
            _stepControl.ActionExpected += StepControlOnActionExpected;
        }

        // Destructor
        ~BaseWPFUserControl()
        {
            // Unsubscribing from the PropertyChanged event of the root
            _stepControl.PropertyChanged -= StepControlOnPropertyChanged;
            _stepControl.ActionExpected -= StepControlOnActionExpected;
        }

        #endregion

        #region Members of IStepControl

        public virtual string Title
        {
            get { return _stepControl.Title; }
        }

        public virtual StepControlStateEnum State
        {
            get { return _stepControl.State; }
            set { _stepControl.State = value; }
        }

        public virtual bool Initialize()
        {
            return _stepControl.Initialize();
        }

        public virtual bool CanMoveIn()
        {
            return _stepControl.CanMoveIn();
        }

        public virtual bool CanMoveOut()
        {
            return _stepControl.CanMoveOut();
        }

        public virtual bool BeforeMovingIn()
        {
            return _stepControl.BeforeMovingIn();
        }

        public virtual bool MoveIn()
        {
            return _stepControl.MoveIn();
        }

        public virtual bool AfterMovingIn()
        {
            return _stepControl.MoveOut();
        }

        public virtual bool BeforeMovingOut()
        {
            return _stepControl.BeforeMovingOut();
        }

        public virtual bool MoveOut()
        {
            return _stepControl.MoveOut();
        }

        public virtual bool AfterMovingOut()
        {
            return _stepControl.AfterMovingOut();
        }

        #region IStepControl.IObservable<T> Members

        public virtual void Attach(StepsManagerLibrary.Interfaces.IObserver<StepControlStateEnum> observer)
        {
            _stepControl.Attach(observer);
        }

        public virtual void Detach(StepsManagerLibrary.Interfaces.IObserver<StepControlStateEnum> observer)
        {
            _stepControl.Detach(observer);
        }

        public virtual void Notify(StepControlStateEnum notification)
        {
            _stepControl.Notify(notification);
        }

        #endregion

        #region Members of IStepControl.INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }

        // When the BaseStepControl property changes, we fire our own
        // PropertyChanged Event handler
        private void StepControlOnPropertyChanged(object sender,
            PropertyChangedEventArgs propertyChangedEventArgs)
        {
            OnPropertyChanged(propertyChangedEventArgs.PropertyName);
        }

        #endregion

        #region IActionInitiator Members

        public bool StartAction(StepActionTypeEnum actionType, 
            ActionEventArgs args)
        {
            return _stepControl.StartAction(actionType, args);
        }

        #endregion

        #region Members of IStepControl.INotificationActionExpected

        public event ActionExpectedEventHandler ActionExpected;

        /// <summary>
        /// Firing an event that inform that an Action has been required from
        /// the current IStepControl
        /// </summary>
        /// <param name="actionType"></param>
        /// <param name="args">Arguments related with the action</param>
        protected virtual void OnActionExpected(StepActionTypeEnum actionType, 
            ActionEventArgs args)
        {
            ActionExpectedEventHandler handler = ActionExpected;
            
            if (handler != null)
            {
                handler(this, actionType, args);
            }
        }

        /// <summary>
        /// Proxy Event Method
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="actionType"></param>
        /// <param name="args"></param>
        private void StepControlOnActionExpected(object sender, StepActionTypeEnum actionType, 
            ActionEventArgs args)
        {
            OnActionExpected(actionType, args);
        }

        #endregion

        #endregion
    }
}
